Pageable filter driver for prospective implementation of disk space quotas

ABSTRACT

A filter driver for implementing disk space quotas is described. Quota limits on disk space taken up by files in the file system are established for users and directories, and an internal database is established to track quotas against actual disk space utilization. A driver in accordance with the invention uses kernel resources of the operating system to prevent execution of file system I/O operations which would violate any established quota. In doing so, the driver executes a logic in kernel mode which serializes file allocation operations and also serializes access to the internal database. The first step in this logic is to intercept file system I/O requests before they reach the file system driver. Then the driver determines propectively—before the I/O request is completed—whether any quota would be exceeded by completion of the I/O request. If a quota would be exceeded, completion of the I/O request is blocked and an error status is issued. It a quota would not be exceeded, the I/O request is allowed to complete and the driver&#39;s internal database is updated with revised disk space utilization data.

This patent application is a continuation in part of provisionalapplication 60/067,671 of the same title filed on Dec. 5, 1997.

BACKGROUND OF THE INVENTION

1. Field of the Invention

The present invention generally relates to devices for managing andcontrolling the allocation of disk space under an operating system, andmore particularly to filter driver techniques for for implementing diskspace quotas.

2. Background Description

Disk space quotas limit the amount of disk space that can be consumed byusers on a system. Disk space is a resource that is necessary for propersystem operation. In the absence of an enforceable disk space quotasystem, users are free to allocate as much disk space as they wish. Thissituation can interfere with system operation, as other users, as wellas the operating system itself, may be unable to allocate disk spacewhen it is needed. A disk space quota system allows system managers toset the maximum amount of disk space that each user may consume,ensuring that there will always be adequate space available for systemoperation.

While quota systems are implemented in many operating systems, someoperating systems do not have quota systems or do not have robust quotafunctionality. For example, Windows NT (through version 4.0) does notprovide a disk space quota system. Since Windows NT is increasinglybeing used in large multi-user server environments, it is necessary forthird parties to provide this functionality. Some have attempted toprovide this functionality using prior art techniques, but the methodsthey have used do not satisfactorily accomplish the goal of limitingdisk space consumption by users.

For example, the prior art for implementing quotas under an operatingsystem such as Windows NT version 4.0, where the operating system doesnot itself provide this functionality, relies upon the operatingsystem's directory change notification mechanism to detect fileallocation changes. Under this approach, if a quota is exceeded fileprotections are changed so that users may no longer create files in thedirectory to which the quota applies. This method is reactive; itdetects changes after they have occurred, and has several disadvantageswhich limit its usefulness:

-   -   1. An appropriate status code cannot be returned. Changing file        protections results in an “Access denied” status.    -   2. Absolute enforcement of quotas is not possible. The prior art        method detects that a quota has already been exceeded. It does        not fail an operation which would exceed a quota.    -   3. Files that are open cannot be affected. Once a user has        opened a file he may extend it to the limit of available disk        space, without being detected or prevented by the prior art        method.

SUMMARY OF THE INVENTION

It is therefore an object of the present invention to implement diskspace quotas in a manner which detects quota violations before they arewritten to disk.

A further object of the invention is to fail a disk I/O operation whichwould exceed a quota.

It is also an object of the invention to apply quotas to files whichhave been opened.

Another object of the invention is to use facilities available in thekernel of the operating system, including synchronization facilities.

A further object of the invention is to be implemented in pageable code.

The present invention is a filter driver for implementing disk spacequotas. Quota limits on disk space taken up by filed in the file systemare established for users and directories, and an internal database isestablished to track quotas against actual disk space utilization. Adriver in accordance with the invention uses kernel resources of theoperating system to prevent execution of file system I/O operationswhich would violate any established quota. In doing so, the driverexecutes a logic in kernel mode which serializes file allocationoperations and also serializes access to the internal database.

The first step in this logic is to intercept file system I/O requestsbefore they reach the file system driver. Then the driver determinesprospectively—before the I/O request is completed—whether any quotawould be exceeded by completion of the I/O request. If a quota would beexceeded, completion of the I/O request is blocked and an error statusis issued. If a quota would not be exceeded, the I/O request is allowedto complete and the driver's internal database is updated with reviseddisk space utilization data.

The invention includes a file system filter driver that has theresponsibility of monitoring disk space usage by users, and enforcingthe quotas established by the system manager for each user. Quotas mayalso be established for directories where files are stored. Theinvention's file system filter driver intercepts every call bound forthe file system driver and processes each of them with respect to theireffect on disk space allocation in relation to the established quotas.

The invention keeps a persistent database of the established quotas andthe amount of disk space used. This database is updated when fileallocation changes, and it is used to store the quota information acrosssystem boots.

By using a file system filter driver to implement quotas, the inventionis able to evaluate the effects of file system operations before theoperation is actually executed. This allows the invention to enforcequotas in real time with a high degree of precision. Since the inventionis in the actual I/O path, it can fail I/Os with the appropriate “QuotaExceeded” status code and can maintain an exact record of fileallocation at any point in time.

BRIEF DESCRIPTION OF THE DRAWINGS

The foregoing and other objects, aspects and advantages will be betterunderstood from the following detailed description of a preferredembodiment of the invention with reference to the drawings, in which:

FIG. 1 is a schematic of prior art techniques for implementing quotas.

FIG. 2 is a flow chart for intercepting I/O requests in accordance withthe invention.

FIG. 3 is a flow chart for IRQL post processing in accordance with theinvention.

DETAILED DESCRIPTION OF A PREFERRED EMBODIMENT OF THE INVENTION

Referring now to the drawings, and more particularly to FIG. 1, there isshown a prior art method of implementing quotas by monitoring changes tothe file system directory. In the prior art a kernel process receives anI/O request 11 and checks the applicable file protections 12. Ifapplicable file protections are violated the I/O request returns “AccessDenied”. If applicable file protections are not violated, the I/Orequest is completed 13 and the NT directory 16 is updated 15. The quotaapplication software 17 detects that an I/O even affecting quotas hasbeen executed and then evaluates 18 whether an affected file protectionin NT directory 16 should be changed as a result of the I/O event. If anaffected file protection should be changed the quota applicationsoftware 17 then changes the file protections 19 in the NT directory 16.This in turn affects whether a subsequent I/O request will be executed.

In contrast to this prior art method, the present invention uses a filesystem filter to implement a quota system. A practical implementation ofthe invention can be described with reference to the Windows NT 4.0operating system. See Inside the Windows NT File System by Helen Custer(Microsoft Press, 1994), which is incorporated herein by this reference,for a description of the environment within which the invention isimplemented, in particular Chapter 2 which describes the layered drivermodel. The present invention is implemented to provide a quota systemfor Windows NT 4.0 as a filter driver on top of the NTFS Driver providedby Windows NT.

A file system filter is a kernel mode driver which intercepts filesystem I/O requests before they reach the file system driver, and mayoptionally specify a routine to be executed after the file system drivercompletes a request. File system drivers are old in the art and havebeen used for on-disk data encryption/decryption, file systemperformance monitoring, and other purposes.

Turning now to FIG. 2, when a file system driver in accordance with theinvention (hereinafter called “QaFilter”) receives a file system I/Orequest 21, it processes it based on the type of request. The I/Orequest is evaluated 22 to determine whether the request, if completed,would have an effect on a quota. Such requests (discussed below) coverfile creation or open, write, change of file ownership, file renaming,and change of file compression status. If an I/O request 21 is one ofthese types 23, QaFilter determines—prospectively—how the various quotaswould be affected if the I/O request were completed 24. If thatdetermination 24 is that a quota would be exceeded, then the I/O requestis failed and the routine returns to the caller 25 with an appropriate“Quota Exceeded” status code 26. If the determination 22 is that noquota would be exceeded, a post processing routine is specified 27 whichwill determine the actual effect of the operation on disk allocation,and the I/O request is completed 28. If an I/O request is determined atthe evaluation step 22 to be not of a type which could have an effect ona quota 29, then it is completed 28.

Further detailes of how QaFilter operates with respect to I/O requestswhich may affect quotas will now be explained.

Create (Open)

A request to open a file causes QaFilter to create internal datastructures (not shown) describing the file and the space currentlyallocated to the file. The allocation size of the file to be opened isretrieved from the file system and stored in the internal datastructures so that the effect on file size of subsequent operations onthe file can be accurately determined.

Write, Set Information (Extend or Truncate)

A write which extends beyond the current allocated space or a SetInformation operation which changes the size of the file will affect theallocation size of the file on disk. QaFilter calculates the change theoperation will have on file allocation. If the change would result inexceeding any applicable quota, the operation is failed immediately with“Quota Exceeded” status. If the change is permissible, a post processingroutine is specified which will be executed after the file system hascompleted the request. The post processing routine examines the actualeffect the operation had on disk space allocation for the file andupdates the data structures for the file, both in memory and in thepersistent database on disk.

Set Security (Change Owner)

Since many quotas are based on file ownership, changing the owner of afile can affect disk space allocation. When a request to change fileownership is received, it is examined to determine if it would put thenew owner over his quota. If so, the request is failed immediately with“Quota Exceeded” status. If the change is permissible, a post processingroute is specified which will be executed after the file system hascompleted the request. The post processing routine determines whetherthe file system successfully changed the file ownership, and if so,updates the in-memory data structures and the persistent database. Theallocation size of the file is subtracted from the quota for the oldowner, and added to the quota for the new owner.

Set Information (Rename)

Renaming a file can cause a change in quotas. A file may be renamed fromone directory to another, which may change the quotas which apply to thedirectory where the file is located. Rename requests are intercepted,and they are examined to determine whether they have any effect onquotas. If the request would result in exceeding any applicable quota,it is failed immediately with a “Quota Exceeded” status. If the changeis permissible, a post processing routine is specified which willexecute after the file system has completed the request. The postprocessing routine examines the effects of the rename operation andupdates the in-memory data structures and persistent databaseappropriately. The size of the renamed file (or multiple files in thecase of a directory rename operation) is subtracted from any quotaswhich no longer apply, and added to any quotas which now apply, butpreviously did not.

File System Control (Set Compression)

Changing the compression status of a file will affect its allocation.When a compressed file is uncompressed, it may cause a user to exceedhis quota. If this would be the case, the request is failed immediatelywith “Quota Exceeded” status. If the uncompress operation ispermissible, or a file is being compressed, a post processing routine isspecified which will execute after the file system has completed therequest. The post processing routine determines the effect of theoperation on disk space allocation and updates the in-memory datastructures and the persistent database appropriately.

Cleanup

When a user closes his handle to a file, QaFilter receives Cleanuprequest. This causes QaFilter to eliminate any in-memory data structuresfor the file which are no longer needed.

Synchronization Issues

In order to accurately detect changes in file size, operations whichmight affect allocation must be serialized. In order to effectserialization, it is necessary to synchronize the operations which arerelated. In Windows NT, this can be accomplished through the use of akernel event, which is one of the synchronization objects made availableby the operating system. A kernel event is associated with each openfile. A kernel event is in one of two states, signaled or non-signaled.Multiple processes can have a handle to a kernel event. When anoperation which might affect file size is detected, the event for thefile is cleared by QaFilter, i.e. reset to the non-signaled or lockedstate. While the event is locked, other operations on the file areblocked, waiting for the event to be signaled. The event is signaled inthe post-processing routing for the operation which cleared the event,effectively serializing operations.

Additionally, QaFilter must serialize access to its internal datastructures. This is done through the use of a single kernel mutex, whichis another synchronization object made available by the Windows NToperating system. A mutex is useful in coordinating mutually exclusiveaccess to a shared resource (thus the name “mutex”). Only one thread ata time can own a particular mutex. In order to access QaFilter'sinternal data structures, a thread must own a single kernel mutex. Thismutex is in a signaled state when it is not owned by any thread, and isreset to a non-signaled or locked state by a thread which needs toaccess those data structures. While so locked, no other thread canaccess those data structures, thus serializing access.Avoiding Recursive Operations

QaFilter must do file system I/O to acquire initial space used valuesand to update its database when necessary. This could cause recursivecalls into QaFilter, resulting in dead-locks if a resource is held. Toavoid this situation, the thread id of the thread which accesses thequota database, and of a thread created to do a file system scan, isrecorded, and any I/O from those threads is ignored by QaFilter andpassed directly to the file system driver.

Paging I/O

Paging I/O does not cause file allocation to change and is ignored.Ignoring paging I/O allows much of the driver's code to be pageable(incurring a page fault while processing a page fault causes a systemcrash), and improves performance by involving QaFilter only whennecessary.

Retrieving Initial File Allocation

In some cases, e.g. when opening a file for overwrite access, QaFiltermust retrieve the size of a file before the file is actually opened.Ordinarily, QaFilter gets the size of a file by doing an I/O against thefile object which represents the user's handle to the file. However,before the file is opened, the file object does not represent a validhandle. In this case, QaFilter opens the file before the user's open isprocessed, getting it's own handle to the file. This handle is used toretrieve the allocation information. Then QaFilter's handle is closed,and the user's open request is allowed to proceed.

Renaming Directories

Renaming a directory which is subject to quotas presents specialproblems. When a directory is renamed, causing the set of quotas whichapply to the directory to change, the sum of the allocation of all thefiles in that directory and all of it's subdirectories must be used toadjust the applicable quotas. This is a case where an operation on onefile (the directory) affects many other files. When such an operationoccurs, QaFilter calculates the allocation size for the entire directoryby doing a “scan”, the same operation which takes place when a new quotais created. This sum is subtracted from all quotas which previouslyapplied to the directory and no longer do, and it is added to all newquotas for the directory.

Flushing on Cleanup

When the user closes his handle to a file, some data he has written maystill be in cache. The size of a file may change when this data iscommitted to disk, particularly in the case of a compressed file, wherethe file allocation will decrease significantly when the data is writtento disk. Since QaFilter can no longer effectively track the file afterthe user's handle is closed, it must force the data to be written to thedisk at this point to get an accurate final file size. It does this byissuing a flush on the file object which represents the user's handlewhen a cleanup operation occurs. This causes the file size to beupdated, and QaFilter can then retrieve an accurate allocation for quotacalculations.

IROL Issues

Windows NT I/O post-processing routines may execute at DISPATCH_LEVEL(IRQL 2) or lower. This causes some complications for QaFilter, becausemany routines should not be called at DISPATCH_LEVEL. For example,taking a page fault or performing I/O at DISPATCH_LEVEL may cause asystem crash. Since QaFilter must access pageable file system datastructures and do I/O to retrieve file sizes and to update the quotadatabase in I/O post-processing, practice of the invention requires amethod to perform these operations without using DISPATCH_LEVEL.

Turning now to FIG. 3, if the filesystem's dispatch routine 31 returneda status other 32 than STATUS_PENDING 33, then the NT I/O completionroutine does not do post-processing. Instead, it just returnsSTATUS_SUCCESS, and the post processing if performed by QaFilter'sdispatch routine 37. This guarantees that the post-processing will bedone at PASSIVE_LEVEL (IRQL 0).

If the filesystem's dispatch routine returned STATUS_PENDING 33, thenQaFilter's dispatch routine has already returned, and the user's I/O maybe asynchronous. This means QaFilter must do other work to guaranteeexecuting the post-processing functions at PASSIVE_LEVEL. If the NT I/Ocompletion routine is executing at PASSIVE_LEVEL (a determination madeat block 34 in FIG. 3), then QaFilter's post-processing routine 37 iscalled directly 38, allowing for greatest performance. If the NT I/Ocompletion routine is called at DISPATCH_LEVEL (a determination made atblock 34 in FIG. 3), then QaFilter's post-processing routine is queued35 to a pool of worker threads which execute at PASSIVE_LEVEL, and theI/O completion is delayed by returning 36STATUS_MORE_PROCESSING_REQUIRED to the I/O Manager. When the workerthread has completed post-processing, it completes the I/O by callingIoCompleteRequest.

The best mode of implementing the features of the invention shown anddescribed in connection with FIG. 3 is further detailed in the followingAppendix, which sets forth the details in programming language whichwill be understood by those skilled in the art.

APPENDIX NTSTATUS FASTCALL set_completion ( PDEVICE_OBJECTdevice_object, PIRP  irp, PQA_COMPLETION_ROUTINE routine, PQFCB qfcb) {NTSTATUS status =3D STATUS_SUCCESS; PDEVICE_OBJECT target_device =3DNULL; PIO_STACK_LOCATION irp_sp =3D NULL; PIO_STACK_LOCATION irp_next_sp=3D NULL; PIRP_CONTEXT irp_context =3D NULL; PFILE_OBJECT   file_obj;PAGED_CODE( ); TraceEnter(“set_completion”); target_device =3D((PFILTER_DEV_EXTENSION) =device_object->DeviceExtension)->fs_device;irp_sp =3D IoGetCurrentIrpStackLocation ( irp); file_obj =3Dirp_sp->FileObject; irp_next_sp =3D IoGetNextIrpStackLocation ( irp);irp_next_sp->MajorFunction =3D irp_sp->MajorFunction;irp_next_sp->MinorFunction =3D irp_sp->MinorFunction; irp_next_sp->Flags=3D irp_sp->Flags; irp_next_sp->Parameters =3D irp_sp->Parameters;irp_next_sp->FileObject =3D irp_sp->FileObject;irp_next_sp->DeviceObject =3D target_device; irp_context =3Dcreate_irp_context ( device_object, irp, qfcb); if (irp_context =3D=3DNULL) { return STATUS_INSUFFICIENT_RESOURCES; }irp_context->completion_routine =3D routine; IoSetCompletionRoutine (irp, post_process, irp_context, TRUE, TRUE, TRUE); status =3DIoCallDriver ( target_device, irp); if (status !=3D STATUS_PENDING) {(VOID) (*routine) ( irp_context); free irp_context ( irp_context); }return status; } NTSTATUS post_process ( PDEVICE_OBJECT devobj, PIRP irp, PIRP_CONTEXT  irp_context) { NTSTATUS   status =3D STATUS SUCCESS;PIO_STACK_LOCATION    irp_sp =3D IoGetCurrentIrpStackLocation(irp); PSID  owner =3D NULL; PQSEC_DESC  sd =3D NULL; // //  If IoCallDriverreturned PENDING, mark our //  stack location with pending. //irp_context->io_status =3D irp->IoStatus.Status; irp_context->io info=3D irp->IoStatus_Information; if (lirp->PendingReturned) { returnSTATUS_SUCCESS; } IoMarkIrpPending( irp ); if (KeGetCurrentIrql ( )=3D=3D PASSIVE_LEVEL) { status =3D (*irp_context->completion routine) (irp_context); free_irp_context ( irp_context); return status; } else {ExInitializeWorkItem ( &irp_context->work_item, work_post, irp_context);QaQueueWorkItem ( &irp_context->work_item, CriticalWorkQueue); returnSTATUS_MORE_PROCESSING_REQUIRED; } } VOID work_post ( PIRP_CONTEXT irp_context) { PAGED_CODE( ); (*irp_context->completion_routine) (irp_context); IoCompleteRequest ( irp_context->irp, IO_NO_INCREMENT);free_irp_context ( irp_context); return; } NTSTATUS FASTCALLsynchronous_completion ( PDEVICE_OBJECT device_object, PIRP  irp,PQA_COMPLETION_ROUTINE routine, PQFCB   qfcb) { NTSTATUS status =3DSTATUS_SUCCESS; NTSTATUS io_call_status =3D STATUS_SUCCESS;PDEVICE_OBJECT target_device =3D NULL; PIO_STACK_LOCATION irp_sp =3DNULL; PIO_STACK_LOCATION irp_next_sp =3D NULL; PIRP_CONTEXT irp_context=3D NULL; PFILE_OBJECT  file_obj; PAGED_CODE( );TraceEnter(“set_completion”); target device =3D ((PFILTER_DEV_EXTENSION)=device_object->DeviceExtension) ->fs_device; irp_sp =3DIoGetCurrentIrpStackLocation ( irp); file_obj =3D irp_sp->FileObject;irp_next_sp =3D IoGetNextIrpStackLocation ( irp);irp_next_sp->MajorFunction =3D irp_sp->MajorFunction;irp_next_sp->MinorFunction =3D irp_sp->MinorFunction; irp_next_sp->Flags=3D irp_sp->Flags; irp_next_sp->Parameters =3D irp_sp->Parameters;irp_next_sp->FileObject =3D irp_sp->FileObject;irp_next_sp->DeviceObject =3D target_device; irp_context =3Dcreate_irp_context ( device_object, irp, qfcb); if (irp_context =3D=3DNULL) { return STATUS_INSUFFICIENT_RESOURCES; }irp_context->completion_routine =3D routine; KeInitializeEvent (&irp_context->event, NotificationEvent, FALSE); IoSetCompletionRoutine (irp, synch_post, irp_context, TRUE, TRUE, TRUE); io_call_status =3DIoCallDriver ( target_device, irp); KeWaitForSingleObject (&irp_context->event, Executive, KernelMode, FALSE, NULL); status =3D(*routine) ( irp_context); ASSERT(status =3D=3D STATUS_SUCCESS);free_irp_context ( irp_context); return io_call_status; } NTSTATUSsynch_post ( PDEVICE_OBJECT devobj, PIRP   irp, PIRP_CONTEXTirp_context) { // // If IoCallDriver returned PENDING, mark our // stacklocation with pending. // if (irp->PendingReturned) { IoMarkIrpPending(irp ); } irp_context->io_status =3D irp->IoStatus.Status;irp_context->io_info =3D irp->IoStatus.Information; KeSetEvent (&irp_context->event, 0, FALSE); return STATUS_SUCCESS; }

While the invention has been described in terms of a single preferredembodiment, those skilled in the art will recognize that the inventioncan be practiced with modification within the spirit and scope of theappended claims.

1. A filter driver for use with an operating system, comprising: meansfor establishing disk space quotas, said quotas being established inrelation to a plurality of quota parameters; means for determining diskspace utilization in relation to each of said quota parameters aplurality of disk space quotas; means for storing said disk space quotasand said disk space utilization in a file structure; means formonitoring disk I/O; means for prospectively evaluating the effect ofsaid disk I/O on said disk space utilization, said effect being arevised disk space utilization in relation to said disk space quotas;means for terminating said disk I/O if said revised disk spaceutilization exceeds any of said disk space quotas; and means forupdating said file structure to reflect completion of said disk I/O ifsaid revised disk space utilization does not exceed any of said diskspace quotas.
 2. The filter driver of claim 1, wherein said monitoringmeans further comprises: means for detecting disk I/O operations, eachsaid disk I/O operation being associated with a named disk file; meansfor serializing operations on said named disk file.
 3. The filter driverof claim 2, wherein said serializing means further comprises: means forlocking a synchronizing object, said synchronizing object beingassociated with said named disk file, and said locking means serving toblock further disk I/O operations on said named disk file.
 4. The filterdriver of claim 3, wherein said synchronizing object is a kernel eventin the Windows NT operating system.
 5. The filter driver of claim 1,wherein said plurality of quota parameters comprise one or moreownership quotas and one or more directory quotas, each said ownershipquota being a maximum quantity of said disk space in use by filesassociated with a particular owner, and each said directory quota beinga maximum quantity of said disk space in use by files associated with aparticular directory.
 6. The filter driver of claim 1, wherein access tosaid file structure is serialized.
 7. The filter driver of claim 1,wherein said monitoring means ignores paging I/O.
 8. The filter driverof claim 1, wherein said prospective evaluation means further comprises:means for determining said revised disk space utilization; and means forcomparing said revised disk space utilization to said disk space quotas.